<template>
  <div class="flex flex-col">
    <div class="flex flex-row mb-2">
      <el-button type="" plain draggable="true" @dragend="handleDragEnd($event)"
        >创建节点
      </el-button>
      <!-- draggable="true"是HTML的拖拽属性  -->
      <WK />
      <!-- 保存按钮 -->
      <el-button type="info" @click="saveGraph" plain>保存</el-button>
      <el-button type="primary" @click="openFullScreen2">
        As a service
      </el-button>
    </div>
    <div class="flex flex-row">
      <div ref="containerRef" id="container"></div>
      <!-- <MiniMap /> -->
      <Note />
    </div>
  </div>
</template>

<script setup>
import { onMounted, ref, watch } from 'vue'
import { Graph, Shape } from '@antv/x6'
import { Snapline } from '@antv/x6-plugin-snapline'
import { Keyboard } from '@antv/x6-plugin-keyboard'
// import { MiniMap } from '@antv/x6-plugin-minimap'
import { Selection } from '@antv/x6-plugin-selection'
import WK from './components/watchKeyboard.vue'
import Note from './components/note.vue'
// import MiniMap from './components/MiniMap.vue'
import { useCookies } from '@vueuse/integrations/useCookies'

const cookie = useCookies()
//添加节点到画布
// 定义节点样式
const commonAttrs = {
  body: {
    fill: '#fff',
    stroke: '#8f8f8f',
    strokeWidth: 1
  },
  label: {
    refX: 0.5,
    refY: '100%',
    refY2: 4,
    textAnchor: 'middle',
    textVerticalAnchor: 'top'
  }
}
// 注册边
Graph.registerEdge('double-edge', {
  inherit: 'edge',
  markup: [
    {
      tagName: 'path',
      selector: 'outline',
      attrs: {
        fill: 'none',
        stroke: '#000000',
        strokeWidth: 6,
        strokeLinejoin: 'round',
        connection: true // 确保这条路径作为连接的一部分
      }
    },
    {
      tagName: 'path',
      selector: 'line',
      attrs: {
        fill: 'none',
        stroke: '#dddddd',
        strokeWidth: 4,
        strokeLinejoin: 'round',
        cursor: 'pointer',
        connection: true // 确保这条路径作为连接的一部分
      }
    }
  ],
  attrs: {
    line: {
      targetMarker: {
        tagName: 'path',
        stroke: '#000000',
        fill: '#000000',
        d: 'M 10 -3 10 -10 -2 0 10 10 10 3'
      }
    }
  }
})
// 注册antv节点
Graph.registerNode(
  'custom-node',
  {
    inherit: 'rect', // 继承于 rect 节点
    width: 100,
    height: 100,
    markup: [
      {
        tagName: 'rect', // 标签名称
        selector: 'body' // 选择器
      },
      {
        tagName: 'image',
        selector: 'img'
      },
      {
        tagName: 'text',
        selector: 'label'
      }
    ],
    attrs: {
      body: {
        stroke: '#8f8f8f',
        strokeWidth: 5,
        fill: '#fff',
        rx: 16,
        ry: 16
      },
      img: {
        'xlink:href':
          'https://gw.alipayobjects.com/zos/antfincdn/FLrTNDvlna/antv.png',
        width: 80,
        height: 80,
        x: 10,
        y: 10
      },
      label: {
        fill: '#000000',
        fontSize: 40
      }
    }
  },
  true
)

// 添加节点
const addHandleNode = (x, y) => {
  graph.value.addNode({
    shape: 'custom-node', // 可以直接使用上面注册过的 shape
    x: x,
    y: y,
    // label: 'name',
    // 连接桩
    ports: {
      groups: {
        groupBottom: {
          position: 'bottom',
          attrs: {
            circle: {
              r: 6,
              magnet: true,
              stroke: '#ffffff',
              strokeWidth: 2,
              fill: '#5F95FF'
            }
          }
        },
        groupRight: {
          position: 'right',
          attrs: {
            circle: {
              r: 6,
              magnet: true,
              stroke: '#ffffff',
              strokeWidth: 2,
              fill: '#5F95FF'
            }
          }
        },
        groupLeft: {
          position: 'left',
          attrs: {
            circle: {
              r: 6,
              magnet: true,
              stroke: '#ffffff',
              strokeWidth: 2,
              fill: '#5F95FF'
            }
          }
        },
        groupTop: {
          position: 'top',
          attrs: {
            circle: {
              r: 6,
              magnet: true,
              stroke: '#ffffff',
              strokeWidth: 2,
              fill: '#5F95FF'
            }
          }
        }
      },
      items: [
        {
          group: 'groupTop',
          id: 'port1'
        },
        {
          group: 'groupBottom',
          id: 'port2'
        },
        {
          group: 'groupLeft',
          id: 'port3'
        },
        {
          group: 'groupRight',
          id: 'port4'
        }
      ]
    },
    zIndex: 10
    // tools: [
    //   {
    //     name: 'button-remove', // 工具名称
    //     args: {
    //       // 工具对应的参数
    //       x: 10,
    //       y: 10
    //     }
    //   }
    // ]
  })
}

// 拖拽释放事件-->调用添加节点方法
const handleDragEnd = e => {
  // $event 是原生 DOM 事件对象，包含了事件的所有信息
  // item 是被拖拽的元素的数据
  // addHandleNode(e.pageX - 700, e.pageY - 510)
  // 将页面坐标转换为画布坐标
  const point = graph.value.clientToLocal(e.clientX, e.clientY)
  // 添加节点到画布
  addHandleNode(point.x - 50, point.y - 50)
}

// 定义图形数据
const data = {
  nodes: [
    {
      id: 'node1',
      shape: 'rect',
      x: 0,
      y: 0,
      width: 100,
      height: 40,
      label: 'hello',
      attrs: {
        body: {
          stroke: '#8f8f8f',
          strokeWidth: 1,
          fill: '#fff',
          rx: 6,
          ry: 6
        }
      }
    },
    {
      id: 'node2',
      shape: 'rect',
      x: 60,
      y: 180,
      width: 100,
      height: 40,
      label: 'world',
      attrs: {
        body: {
          stroke: '#8f8f8f',
          strokeWidth: 1,
          fill: '#fff',
          rx: 6,
          ry: 6
        }
      }
    }
  ],
  edges: [
    {
      shape: 'edge',
      source: 'node1',
      target: 'node2',
      label: 'html',
      attrs: {
        line: {
          stroke: '#8f8f8f',
          strokeWidth: 1
        }
      }
    }
  ]
  // graph: null //画布实例对象
}

// 获取dom节点
const containerRef = ref(null)
// 定义画布实例
const graph = ref(null)
// 定义画布
const initGraph = () => {
  graph.value = new Graph({
    container: containerRef.value,
    // width: 800,
    // height: 600,
    background: {
      color: '#FDF6E3'
    },
    // 画布网格配置
    grid: {
      visible: true,
      type: 'doubleMesh',
      size: 10, //设置网格大小
      args: [
        {
          color: '#eee', // 主网格线颜色
          thickness: 1 // 主网格线宽度
        },
        {
          color: '#ddd', // 次网格线颜色
          thickness: 2, // 次网格线宽度
          factor: 10 // 主次网格线间隔
        }
      ]
    },
    // 配置连线规则
    connecting: {
      snap: true, // 自动吸附
      allowBlank: false, // 是否允许连接到画布空白位置的点
      allowMulti: true, // 是否允许在相同的起始节点和终止之间创建多条边
      allowLoop: false, // 是否允许创建循环连线，即边的起始节点和终止节点为同一节点
      highlight: true, // 拖动边时，是否高亮显示所有可用的节点
      highlighting: {
        magnetAdsorbed: {
          name: 'stroke',
          args: {
            attrs: {
              fill: '#5F95FF',
              stroke: '#5F95FF'
            }
          }
        }
      },
      // 如果没有 args 参数，可以简写写 router: 'metro'
      router: {
        name: 'metro',
        args: {}
      },
      // 如果没有 args 参数，可以简写写 connector: 'rounded'
      connector: {
        name: 'rounded',
        args: {
          radius: 10
        }
      }
    },
    snapline: true, // 对齐线
    panning: true,
    // 按下ctrl可以缩放
    mousewheel: {
      enabled: true,
      modifiers: ['ctrl']
    }
  })
  // 增加对齐线功能
  graph.value.use(
    new Snapline({
      enabled: true
    })
  )
  graph.value.resize(800, 600) // resize 画布大小
  // graph.zoomTo(1.5) // 将画布缩放级别设置为 1.2
  graph.value.zoomToFit({ maxScale: 1 })
  graph.value.centerContent() // 将画布中元素居中展示
  graph.value.fromJSON(data)
  // 使用快捷键
  graph.value.use(
    new Keyboard({
      enabled: true
    })
  )
  // 框选功能
  graph.value.use(
    new Selection({
      enabled: true, // 开启框选功能
      className: 'my-selecting', // 框选框样式名
      multiple: true, // 允许多选
      multipleSelectionModifiers: ['ctrl'], //多选配套的修饰键
      rubberband: true, // 允许框选
      modifiers: ['ctrl'], //框选配套的修饰键
      strict: false, //是否需要完全包围节点时才选中节点
      movable: true, // 允许移动选中的元素
      showNodeSelectionBox: true, // 显示节点选择框
      showEdgeSelectionBox: true, // 显示边选择框
      pointerEvents: 'none' // 设置选择框的 pointer-events 属性
    })
  )
}

// 定义全局变量跟踪选中节点、线条
// const currentSelectedNode = ref(null)
// const currentSelectedEdge = ref(null)
// 鼠标处理事件
const handleEvent = () => {
  const container = containerRef.value
  // const selectNode = ref()
  // const selectEdge = ref(false)

  // 定义节点工具
  const addNodeTools = cell => {
    cell.addTools([
      // {
      //   name: 'boundary',
      //   args: {
      //     attrs: {
      //       fill: '#F0E2BD',
      //       stroke: '#333',
      //       'stroke-width': 1,
      //       'fill-opacity': 0.2
      //     }
      //   }
      // },
      {
        name: 'button-remove',
        args: {
          x: '-5%',
          y: '-5%',
          offset: { x: 0, y: 0 }
        }
      }
    ])
  }
  // 定义边工具
  const addEdgeTools = cell => {
    cell.addTools([
      {
        name: 'boundary',
        useCellGeometry: false,
        args: {
          attrs: {
            fill: '#F0E2BD',
            stroke: '#333',
            'stroke-width': 1,
            'fill-opacity': 0.2
          }
        }
      },
      {
        name: 'button-remove',
        args: {
          x: '100%',
          y: 0,
          offset: {
            x: 0,
            y: 0
          }
        }
      }
    ])
    cell.setAttrs({
      line: {
        stroke: '#D7AE46',
        strokeWidth: 5
      }
    })
    cell.zIndex = 99 // 保证当前悬停的线在最上层，不会被遮挡
  }

  // 节点绑定悬浮事件
  const changePortsVisible = visible => {
    const ports = container.querySelectorAll('.x6-port-body')
    for (let i = 0, len = ports.length; i < len; i = i + 1) {
      ports[i].style.visibility = visible ? 'visible' : 'hidden'
    }
  }
  graph.value.on('node:mouseenter', () => {
    changePortsVisible(true)
  })
  graph.value.on('node:mouseleave', () => {
    changePortsVisible(false)
  })
  // 鼠标点击节点事件
  graph.value.on('node:selected', ({ cell }) => {
    // 已经使用AntV内置框选插件实现
    // // 如果没有节点被选中，或者选中的节点不是当前点击的节点
    // if (!currentSelectedNode.value || currentSelectedNode.value !== cell) {
    //   // 如果之前有节点被选中，移除其工具集
    //   if (currentSelectedNode.value) {
    //     currentSelectedNode.value.removeTools()
    //   }
    //   // 更新当前选中的节点
    //   currentSelectedNode.value = cell
    //   // 添加工具集
    //   addNodeTools(cell)
    // } else {
    //   // 如果点击的是已选中的节点，切换工具集的显示状态
    //   if (selectNode.value) {
    //     // 如果工具集显示，移除工具集
    //     cell.removeTools()
    //     selectNode.value = false
    //   } else {
    //     // 如果工具集隐藏，添加工具集
    //     addNodeTools(cell)
    //     selectNode.value = true
    //   }
    // }
    addNodeTools(cell)
  })

  // 连线绑定悬浮事件
  graph.value.on('cell:mouseenter', ({ cell }) => {
    cell.setAttrs({
      line: {
        stroke: '#D7AE46',
        strokeWidth: 5
      }
    })
  })
  graph.value.on('cell:mouseleave', ({ cell }) => {
    cell.setAttrs({
      line: {
        stroke: 'black',
        strokeWidth: 2 // 将strokeWidth设置为数值
      }
    })
  })
  // // 鼠标点击线条事件
  // graph.value.on('cell:click', ({ cell }) => {
  //   // 已经使用AntV内置框选插件实现
  //   // // 如果没有线条被选中，或者选中的线条不是当前点击的线条
  //   // if (!currentSelectedEdge.value || currentSelectedEdge.value !== cell) {
  //   //   // 如果之前有线条内被选中，移除其工具集
  //   //   if (currentSelectedEdge.value) {
  //   //     currentSelectedEdge.value.removeTools()
  //   //   }
  //   //   // 更新当前选中的线条
  //   //   currentSelectedEdge.value = cell
  //   //   // 添加工具集
  //   //   addEdgeTools(cell)
  //   // } else {
  //   //   // 如果点击的是已选中的节点，切换工具集的显示状态
  //   //   if (selectEdge.value) {
  //   //     // 如果工具集显示，移除工具集
  //   //     cell.removeTools()
  //   //     selectEdge.value = false
  //   //   } else {
  //   //     // 如果工具集隐藏，添加工具集
  //   //     addEdgeTools(cell)
  //   //     selectEdge.value = true
  //   //   }
  //   // }
  //   // currentSelectedNode.value = cell
  // })
  // 绑定键盘快捷键
  graph.value.bindKey(['delete', 'backspace'], () => {
    // 原生方法-->API
    // if (currentSelectedNode.value) {
    // graph.value.removeCells([currentSelectedNode.value])
    //   currentSelectedNode.value = null // 清除当前选中的节点
    // }
    // if (currentSelectedEdge.value) {
    // graph.value.removeCells([currentSelectedEdge.value])
    //   currentSelectedEdge.value = null
    // }
    // return false // 阻止默认行为
    graph.value.removeCells(graph.value.getSelectedCells())
  })
}

// 保存
const saveGraph = () => {
  const data = graph.value.toJSON() // 将画布数据转换为 JSON
  console.log(data) // 控制台输出数据，或进行其他保存操作
  // 例如，保存到本地存储
  cookie.set('graphData-cookie', JSON.stringify(data))
  localStorage.setItem('graphData-localStorage', JSON.stringify(data))
  // 或发送到服务器
  // axios.post('/api/save', data).then(response => {
  //   console.log(response);
  // });
}

// 组件挂载时
onMounted(() => {
  initGraph()
  // initMiniMap()
  handleEvent()
})
</script>

<style lang="scss">
.my-selecting {
  /* 自定义框选样式 */
  border: 2px dashed #00884f8d;
  background-color: rgba(75, 158, 223, 0.1);
}
.x6-widget-selection-box {
  border: 2px dashed #dd4b23;
  background-color: rgba(75, 158, 223, 0.1);
}

.x6-widget-selection-inner {
  border: 1px solid #239edd;
}
</style>
